package com.nulldev.util.java;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.SecureRandom;
import java.util.LinkedList;

import com.nulldev.util.FinalBypass;
import com.nulldev.util.other.RandomUtils.nSecureRandom;

public class CloneUtils {

	public static Object clone(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                field.set(clone, field.get(obj));
            }
            return clone;
        }catch(Exception e){
        	e.printStackTrace();
            return null;
        }
    }

	public static Object cloneObject(Object obj){
        try{
            Object clone = obj.getClass().newInstance();
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                if(field.getType().isPrimitive() || field.getType().equals(String.class)
                        || field.getType().getSuperclass().equals(Number.class)
                        || field.getType().equals(Boolean.class)){
                    field.set(clone, field.get(obj));
                }else{
                    Object childObj = field.get(obj);
                    if(childObj == obj){
                        field.set(clone, clone);
                    }else{
                        field.set(clone, cloneObject(field.get(obj)));
                    }
                }
            }
            return clone;
        }catch(Exception e){
        	e.printStackTrace();
            return null;
        }
    }

	public static BufferedImage clone(final BufferedImage in) {
		final BufferedImage out = new BufferedImage(in.getWidth(), in.getHeight(), in.getType());
		final Graphics2D g2d_in = (Graphics2D) in.getGraphics();
		final Graphics2D g2d_out = (Graphics2D) out.getGraphics();
		final FinalBypass<Boolean> done = new FinalBypass<Boolean>(false);
		/**
		 * 		for (int x = 0; x < in.getWidth(); x++) {
			for (int y = 0; y < in.getHeight(); y++) {
				g2d_out.setColor(new Color(in.getRGB(x, y)));
				g2d_out.drawRect(x, y, 1, 1);
				g2d_out.fillRect(x, y, 1, 1);
			}
			}
		}
		 */
		for (int x = 0; x < in.getWidth(); x++) {
			for (int y = 0; y < in.getHeight(); y++) {
				g2d_out.setColor(new Color(in.getRGB(x, y)));
				//g2d_out.drawRect(x, y, 1, 1);
				g2d_out.fillRect(x, y, 1, 1);
			}
		}
		return out;
	}

	public static String[] createBuffer(final int junkSize) {
		final LinkedList<String> data = new LinkedList<String>();
		final nSecureRandom sr = new nSecureRandom();
		
		for (int i = 0; i < junkSize; i++) {
			data.add(String.valueOf(sr.nextInt()));
		}

		return data.toArray(new String[junkSize]);
	}
}
